package org.dei.perla.sys.core;

import java.io.BufferedReader;
import java.io.StringReader;
import java.util.ArrayList;

import org.dei.perla.parser.grammar.*;
import org.dei.perla.parser.statements.*;
import org.dei.perla.sys.core.exception.AgentRegisrtyException;
import org.dei.perla.utils.pipe.*;
import org.dei.perla.utils.waiter.Waitable;
import org.dei.perla.utils.waiter.Waiter;

public class QueryParserAgent extends DefaultAgent<String, Query>  {
	private static boolean firstTime = true;
	private Waiter<Pipe<String>> queryWaiter = null;
	private Pipe<Boolean> parserQueryStatus = null;
	
	protected QueryParserAgent(String parName) throws AgentRegisrtyException {
		super(parName);
		parserQueryStatus  = new Pipe<Boolean>("Query Parser Status");
		parserQueryStatus.start();
	}
	
	
	public synchronized Query parse(String query) {
		Query queryParsed = null;
		StringReader reader = new StringReader(query);
		BufferedReader bufferedReader = new BufferedReader(reader);
		if(firstTime){
			firstTime = false;
			new Parser(bufferedReader);
		}
		else{
			Parser.ReInit(bufferedReader);
		}
		try {
			queryParsed = Parser.StatementSequence();
		} catch (ParseException e) {
			e.printStackTrace();
			return null;
		}
		return queryParsed;
	}

	@Override
	public void setInputPipe(Pipe<String> defaultPipe) {
		super.setInputPipe(defaultPipe);		
		queryWaiter = new Waiter<Pipe<String>>();
		queryWaiter.start();
		queryWaiter.addWaitable(pipeInput.getWaitable());
	}

	public Pipe<Boolean> getParserQueryStatus() {
		return parserQueryStatus;
	}


	@Override
	public ArrayList<String[]> inspect() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	protected void loop() throws Exception {
		Waitable<Pipe<String>> waitable;
		String toParse;

		while(true) {
			waitable = queryWaiter.waitNext();
			toParse = waitable.getParentComponent().dequeue();
			if (toParse != null) {
				Query queryParsed = parse(toParse);
	//			queryPipe.enqueue(queryParsed);
					
			} else {
				// Killpacket ricevuto, chiudo la connessione con il DB,
				// termino le pipe, termino il processo
				queryWaiter.removeWaitable(waitable);
				waitable.getParentComponent().stop();
				queryWaiter.stop();
				//TODO rivedere questo punto
				break;
			}
		}
		
	}

	@Override
	public void respawn() {
		// TODO Auto-generated method stub
		
	}
	
}
